package com.crawel.utils;

import com.alibaba.fastjson.JSONObject;
import org.apache.http.*;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.*;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.conn.ConnectionKeepAliveStrategy;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicHeaderElementIterator;
import org.apache.http.protocol.HTTP;
import org.apache.http.protocol.HttpContext;
import org.apache.http.util.EntityUtils;

import java.util.List;
import java.util.Map;

/**
 * @program: SpringBootDemos
 * @description: http请求工具  搞个连接池
 * @author: Kangsen
 * @create: 2022-06-10 09:31
 **/

public class HttpPoolUtils {
    public static PoolingHttpClientConnectionManager cm = null;
    public static CloseableHttpClient httpClient = null;
    /** * 默认content 类型 */
    private static final String DEFAULT_CONTENT_TYPE = "application/json";
    private static final String DEFAULT_CHARSET = "UTF-8";
    /** 默认超时时间 */
    private static final int DEFAULT_TIME_OUT = 15;
    private static final int count = 60;
    private static final int totalCount = 300;
    private static final int HTTP_DEFAULT_KEEP_TIME =15;

    /**
     *
     * @DESCRIPTION:初始化连接池
     */
    public static synchronized void initPools() {
        if (httpClient == null) {
            cm = new PoolingHttpClientConnectionManager();
            cm.setDefaultMaxPerRoute(count);
            cm.setMaxTotal(totalCount);
            httpClient = HttpClients.custom().setKeepAliveStrategy(connectionKeepAliveStrategy).setConnectionManager(cm).build();
        }
    }
    /**
     *  Http connection keepAlive 设置
     */
    private static ConnectionKeepAliveStrategy connectionKeepAliveStrategy = new ConnectionKeepAliveStrategy() {
        public long getKeepAliveDuration(HttpResponse response, HttpContext context) {
            HeaderElementIterator it = new BasicHeaderElementIterator(response.headerIterator(HTTP.CONN_KEEP_ALIVE));
            int keepTime = HTTP_DEFAULT_KEEP_TIME;
            while (it.hasNext()) {
                HeaderElement he = it.nextElement();
                String param = he.getName();
                String value = he.getValue();
                if (value != null && param.equalsIgnoreCase("timeout")) {
                    try {
                        return Long.parseLong(value) * 1000;
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
            return keepTime * 1000L;
        }
    };

    public static CloseableHttpClient getHttpClient() {
        return httpClient;
    }

    public static PoolingHttpClientConnectionManager getHttpConnectionManager() {
        return cm;
    }


    /**
     * 执行http post 请求
     * 默认采用Content-Type：application/json，Accept：application/json
     * @param uri 请求地址
     * @param nvps 参数 body 内容
     * @param contentType
     * @param headers
     * @return
     */
    public static String executePost(String uri, List<NameValuePair> nvps, String contentType, Map<String, String> headers) {
        HttpEntity httpEntity = null;
        HttpEntityEnclosingRequestBase method = null;
        String responseBody = "";
        try {
            if (httpClient == null) {
                initPools();
            }
            method = (HttpEntityEnclosingRequestBase) getRequest(uri, HttpPost.METHOD_NAME, contentType==null?DEFAULT_CONTENT_TYPE:contentType, 0, headers);
            StringEntity stringEntity = null;
            if (ContentType.APPLICATION_JSON.getMimeType().contains(contentType)) {
                JSONObject paramMap = new JSONObject();
                if(nvps!=null && nvps.size()>0) {
                    for(NameValuePair nvp : nvps) {
                        paramMap.put(nvp.getName(), nvp.getValue());
                    }
                }
                stringEntity = new StringEntity((nvps != null && nvps.size() != 0) ? paramMap.toJSONString() : "", ContentType.APPLICATION_JSON);
            } else {
                stringEntity = new UrlEncodedFormEntity(nvps, DEFAULT_CHARSET);
            }
            stringEntity.setContentEncoding(DEFAULT_CHARSET);
            stringEntity.setContentType(contentType==null?DEFAULT_CONTENT_TYPE:contentType);
            method.setEntity(stringEntity);
            HttpContext context = HttpClientContext.create();
            CloseableHttpResponse httpResponse = httpClient.execute(method, context);
            httpEntity = httpResponse.getEntity();
            if (httpEntity != null) {
                responseBody = EntityUtils.toString(httpEntity, DEFAULT_CHARSET);
            }
        } catch (Exception e) {
            if (method != null) {
                method.abort();
            }
        } finally {
            if (httpEntity != null) {
                try {
                    EntityUtils.consumeQuietly(httpEntity);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        return responseBody;
    }

    /**
     * get 请求
     * @param uri
     * @param contentType
     * @param headers
     * @return
     */
    public static String executeGet(String uri, String contentType, Map<String, String> headers) {
        HttpEntity httpEntity = null;
        HttpRequestBase method = null;
        String responseBody = "";
        try {
            if (httpClient == null) {
                initPools();
            }
            method = getRequest(uri, HttpGet.METHOD_NAME,  contentType==null?DEFAULT_CONTENT_TYPE:contentType, 0, headers);
            HttpContext context = HttpClientContext.create();
            CloseableHttpResponse httpResponse = httpClient.execute(method, context);
            httpEntity = httpResponse.getEntity();
            if (httpEntity != null) {
                responseBody = EntityUtils.toString(httpEntity, DEFAULT_CHARSET);
            }
        } catch (Exception e) {
            if (method != null) {
                method.abort();
            }
            e.printStackTrace();
        } finally {
            if (httpEntity != null) {
                try {
                    EntityUtils.consumeQuietly(httpEntity);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        return responseBody;
    }

    private static HttpRequestBase getRequest(String uri, String methodName, String contentType, int timeout, Map<String, String> headers) {
        if (httpClient == null) {
            initPools();
        }
        HttpRequestBase method = null;
        if (timeout <= 0) {
            timeout = DEFAULT_TIME_OUT;
        }
        RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(timeout * 1000)
                .setConnectTimeout(timeout * 1000).setConnectionRequestTimeout(timeout * 1000)
                .setExpectContinueEnabled(false).build();
        if (HttpPut.METHOD_NAME.equalsIgnoreCase(methodName)) {
            method = new HttpPut(uri);
        } else if (HttpPost.METHOD_NAME.equalsIgnoreCase(methodName)) {
            method = new HttpPost(uri);
        } else if (HttpGet.METHOD_NAME.equalsIgnoreCase(methodName)) {
            method = new HttpGet(uri);
        } else {
            method = new HttpPost(uri);
        }
        if (contentType==null||"".equals(contentType)) {
            contentType = DEFAULT_CONTENT_TYPE;
        }
        if (headers!=null && headers.keySet().size() > 0) {
            for (String key : headers.keySet()) {
                method.addHeader(key, headers.get(key));
            }
        }
        method.addHeader("Content-Type", contentType);
        method.addHeader("Accept", contentType);
        method.setConfig(requestConfig);
        return method;
    }

}
